package com.momo.theta.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.momo.theta.properties.RedisCacheProperties;
import java.time.Duration;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

@Slf4j
@AllArgsConstructor
@EnableCaching
@EnableConfigurationProperties(RedisCacheProperties.class)
@ConditionalOnProperty(prefix = "spring.redis.cache", name = "enable", havingValue = "true")
public class RedisCacheConfig extends CachingConfigurerSupport {


  private RedisCacheProperties cacheProperties;


  /**
   * 这个是@Cacheable 相关使用
   *
   * @param redisConnectionFactory
   * @return
   */
  @Bean
  public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
        ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(
        Object.class);
    jackson2JsonRedisSerializer.setObjectMapper(mapper);
    RedisCacheConfiguration config = configuration
        .serializeValuesWith(
            RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
        .entryTtl(Duration.ofMinutes(cacheProperties.getTtl()))
        .computePrefixWith(cacheName -> cacheProperties.getPrefix() + "_" + cacheName + "::");
    return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();
  }

}
